package cn.tedu.csmall.product.service.impl;

import cn.tedu.csmall.commons.ex.ServiceException;
import cn.tedu.csmall.commons.util.PageInfoToPageDataConverter;
import cn.tedu.csmall.commons.vo.PageData;
import cn.tedu.csmall.commons.web.ServiceCode;
import cn.tedu.csmall.product.mapper.*;
import cn.tedu.csmall.product.pojo.entity.*;
import cn.tedu.csmall.product.pojo.param.CategoryAddNewParam;
import cn.tedu.csmall.product.pojo.param.CategoryUpdateInfoParam;
import cn.tedu.csmall.product.pojo.vo.CategoryListItemVO;
import cn.tedu.csmall.product.pojo.vo.CategoryStandardVO;
import cn.tedu.csmall.product.pojo.vo.CategoryTreeItemVO;
import cn.tedu.csmall.product.service.ICategoryService;
import com.alibaba.druid.pool.ha.selector.StickyRandomDataSourceSelector;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Administrator
 * @description 针对表【pms_category(类别)】的数据库操作Service实现
 * @createDate 2023-06-13 10:34:27
 */
@Service
@Slf4j
public class CategoryServiceImpl implements ICategoryService {


    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private BrandCategoryMapper brandCategoryMapper;

    @Autowired
    private CategoryAttributeTemplateMapper categoryAttributeTemplateMapper;

    @Autowired
    private SpuMapper spuMapper;


    @Override
    public void addNew(CategoryAddNewParam categoryAddNewParam) {
        log.info("开始处理[添加类别]的业务");
        log.debug("参数:{}", categoryAddNewParam);
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", categoryAddNewParam.getName());
        queryWrapper.eq("parent_id", categoryAddNewParam.getParentId());
        int countByName = categoryMapper.selectCount(queryWrapper);
        log.debug("根据类别名称统计匹配的类别数量，结果:{}", countByName);
        if (countByName > 0) {
            log.info("不满足类型新增规则[同父级类别下不能有相同名称]，抛出异常...");
            String message = "添加类别失败，类别名称已经被占用";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //输入的parentID,父级ID值
        Long parentId = categoryAddNewParam.getParentId();
        //预设为null
        CategoryStandardVO standardById = null;
        //深度预设为1
        Integer depth = 1;
        //如果parentID不等于0，也就是有父级，不是顶级
        if (parentId != 0) {
            //查询父级信息
            standardById = categoryMapper.getStandardById(parentId);
            //如果父级信息不存在抛出异常
            if (standardById == null) {
                String message = "添加类别失败，父级类别不存在";
                log.info("不满足类别新增规则[父级类别必须存在或为0]，抛出异常");
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            } else {
                //如果存在=父级的深度再加1
                depth = standardById.getDepth() + 1;
            }

        }
        log.info("开始添加类别");

        //名称未占用，添加类别到数据库
        Category category = new Category();
        BeanUtils.copyProperties(categoryAddNewParam, category);
        //设置类别的深度，是否为父级，时间等等。。。。
        category.setDepth(depth)
                .setIsParent(0)
                .setGmtCreate(LocalDateTime.now())
                .setGmtModified(LocalDateTime.now());
        log.debug("准备将新的类别数据写入到数据库,数据：{}", category);
        int rows = categoryMapper.insert(category);
        if (rows != 1) {
            String message = "添加属性模版失败！服务器忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }

        log.info("将新的类别数据写入到数据库，完成！");

        //如果父级ID不等于0，有父级，    或者父级的isParent是否为0,==把新增数据添加到目标父级的子级下
        if (parentId != 0 && standardById.getIsParent() == 0) {
            Category parentCategory = new Category();
            parentCategory.setId(parentId)
                    .setIsParent(1);

            rows = categoryMapper.updateById(parentCategory);
            if (rows != 1) {
                String message = "添加属性模版失败！服务器忙，请稍后再试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_UPDATE, message);
            }
            log.info("将新的类别父级数据写入到数据库，完成！");
        }


    }


    @Override
    public void delete(Long id) {
        log.info("开始处理删除类别的业务...");
        log.debug("参数：id={}", id);

        //检查列别ID检查列别是否存在数据，如果不存在，则抛出异常
        CategoryStandardVO categoryStandardVO = categoryMapper.getStandardById(id);
        log.info("根据类别id查询的数据库结果,categoryStandardVO={}", categoryStandardVO);
        if (categoryStandardVO == null) {
            String message = "删除类别失败，类别数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //检查类别是否为父级，如果是，则抛出异常
        log.info("开始检查，类别是否为父级");
        log.debug("类别是否为父级：{}", categoryStandardVO.getIsParent());
        if (categoryStandardVO.getIsParent() == 1) {
            String message = "删除类别失败，该类别为父级";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }


        //检查是否有品牌与类别关联关联到了此类别，如果存在，则抛出异常
        QueryWrapper<BrandCategory> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("category_id", id);
        int countByAlbumId1 = brandCategoryMapper.selectCount(queryWrapper1);
        log.debug("根据类别ID统计匹配的品牌于类别关联数量，结果:{}", countByAlbumId1);
        //如果类别存在大于0
        if (countByAlbumId1 > 0) {
            String message = "删除类别失败，仍有品牌与类别关联关联到此类别";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //检查是否有属性模版到了此类别，如果存在，则抛出异常
        QueryWrapper<CategoryAttributeTemplate> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("category_id", id);
        int countByAlbumId2 = categoryAttributeTemplateMapper.selectCount(queryWrapper2);
        log.debug("根据类别ID统计匹配的属性模版数量，结果:{}", countByAlbumId2);
        if (countByAlbumId2 > 0) {
            String message = "删除类别失败，仍有属性模版关联到此类别";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        //检查是否有SPU关联到了此类别，如果存在，则抛出异常
        QueryWrapper<Spu> queryWrapper3 = new QueryWrapper<>();
        //                      字段值
        queryWrapper3.eq("category_id", id);
        int countByAlbumId3 = spuMapper.selectCount(queryWrapper3);
        log.debug("根据类别ID统计匹配的SPU数量，结果:{}", countByAlbumId3);
        //如果类别存在大于0
        if (countByAlbumId3 > 0) {
            String message = "删除类别失败，仍有SPU关联到此类别";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        log.info("开始处理删除相册的请求");
        int rows = categoryMapper.deleteById(id);
        if (rows != 1) {
            String message = "修改相册失败！服务器忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        log.info("删除类别结果==", rows);
        log.info("删除类别成功！");

        //判断是否修改父级
        QueryWrapper<Category> categoryQueryWrapper = new QueryWrapper<>();
        categoryQueryWrapper.eq("parent_id", categoryStandardVO.getParentId());
        Integer count = categoryMapper.selectCount(categoryQueryWrapper);
        // 如果删除的是最后一个子级，修改父级isParent为0
        if (count == 0) {
            Category parentcategory = new Category();
            parentcategory.setId(categoryStandardVO.getParentId());
            parentcategory.setIsParent(0);
            rows = categoryMapper.updateById(parentcategory);
            if (rows != 1) {
                String message = "修改相册失败！服务器忙，请稍后再试！";
                log.warn(message);
                throw new ServiceException(ServiceCode.ERR_INSERT, message);
            }

            log.info("修改父级类别成功！");

        }

    }

    @Override
    public void updateInfoById(Long id, CategoryUpdateInfoParam categoryUpdateInfoParam) {
        log.info("根据id更新类别");
        log.debug("传入参数,id={},categoryUpdateInfoParam={}", id, categoryUpdateInfoParam);

        //检查类别ID检查类别是否存在数据，如果不存在，则抛出异常
        CategoryStandardVO categoryStandardVO = categoryMapper.getStandardById(id);
        log.info("规则：根据类别id检索数据库结果,categoryStandardVO={}", categoryStandardVO);
        if(categoryStandardVO == null){
            String message = "更新类别失败，类别数据不存在！";
            log.info("根据类别id检索数据量为0，抛出异常...");
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        //检查类别名称是否被占用，如果被占用，则抛出异常
        QueryWrapper<Category> queryWrapper4 = new QueryWrapper<>();
        queryWrapper4.eq("name",categoryUpdateInfoParam.getName());
        queryWrapper4.eq("parent_id",categoryStandardVO.getParentId());
        int countByName = categoryMapper.selectCount(queryWrapper4);
        log.info("业务：根据类别名称检索数据库结果,countByName={}", countByName);
        if(countByName > 0){
            log.info("不满足类别更新规则【同父级类别下不能有相同名称】，抛出自定异常...");
            String message = "更新类别失败，类别名称已经被占用！";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        Category category = new Category();
        BeanUtils.copyProperties(categoryUpdateInfoParam, category);
        category.setId(id);
        int rows = categoryMapper.updateById(category);
        if(rows != 1){
            String message = "编辑类别失败，服务器忙，请稍后再试！";
            log.info("数据返回行数不满足预估行数，预估={}, 实际={}, 抛出自定异常...", 1, rows);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
        log.info("更新成功！！！");

    }

    @Override
    public CategoryStandardVO getStandardById(Long id) {
        log.info("开始:【根据ID查询类别】");
        log.debug("传入参数,id={}", id);
        CategoryStandardVO standardById = categoryMapper.getStandardById(id);

        //根据类别ID检查类别是否存在数据，如果不存在，则抛出异常
        if (standardById == null) {
            log.info("根据类别id查询详情，结果为null，抛出异常...");
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, "查询类别详情失败，类别数据不存在");
        }

        log.info("查询出数据,standardById");
        return standardById;
    }

    @Override
    public List<CategoryListItemVO> listByParentId(Long parentId) {
        List<CategoryListItemVO> categoryListItemVO = categoryMapper.listByParentId(parentId);
        return categoryListItemVO;
    }

    @Override
    public PageData<CategoryListItemVO> listByParentId(Long parentId, Integer pageNum) {
        Integer pageSize = 5;
        return listByParentId(parentId, pageNum, pageSize);
    }

    @Override
    public PageData<CategoryListItemVO> listByParentId(Long parentId, Integer pageNum, Integer pageSize) {
        log.info("开始:【查询-类别-分页】");
        log.debug("传入参数, parentId={}, pageNum={}, pageSize={}", parentId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<CategoryListItemVO> list = categoryMapper.listByParentId(parentId);
        PageInfo<CategoryListItemVO> pageInfo = new PageInfo<>(list);
        PageData<CategoryListItemVO> pageData = PageInfoToPageDataConverter.convert(pageInfo);
        log.debug("结果1: 查询结果：pageData={}", pageData);
        return pageData;
    }



    //修改启用
    @Override
    public void setEnable(Long id) {
        updateEnableById(id, 1);

    }

    //修改禁用
    @Override
    public void setDisable(Long id) {
        updateEnableById(id, 0);

    }


    //修改显示在导航栏
    @Override
    public void setDisplay(Long id) {
        updateDisableById(id, 1);


    }

    //禁用显示在导航栏
    @Override
    public void setHidden(Long id) {
        updateDisableById(id, 0);

    }

    //启用状态
    private void updateEnableById(Long id, int enable) {
        String text = ENABLE_TEXT[enable];
        log.info("开始:【" + text + "类别】");
        log.debug("传入参数,id={}, enable={} ", id, enable);

        //检查数据是否存在，如果不存在，则抛出异常
        CategoryStandardVO categoryStandardVO = categoryMapper.getStandardById(id);
        log.info("规则：根据类别id检索数据库结果,categoryStandardVO={}", categoryStandardVO);
        if (categoryStandardVO == null){
            String message = text + "类别失败，类别数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        if (categoryStandardVO.getEnable().equals(enable)){
            String message = text + "类别失败，此类别已经处于" + text + "状态！";
            log.info("根据类别启用状态与要修改状态一致，抛出异常...");
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        Category category = new Category();
        category.setId(id)
                .setEnable(enable);
        int rows = categoryMapper.updateById(category);
        if (rows != 1) {
            String message = "修改是否启用失败！服务器忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        log.info("修改启用成功！");

    }

    //是否显示在导航栏
    private void updateDisableById(Long id, int enable) {

        String text = DISPLAY_TEXT[enable];
        log.info("开始:【" + text + "类别】");
        log.debug("传入参数,id={}, enable={} ", id, enable);

        //检查数据是否存在，如果不存在，则抛出异常
        CategoryStandardVO categoryStandardVO = categoryMapper.getStandardById(id);
        log.info("规则：根据类别id检索数据库结果,categoryStandardVO={}", categoryStandardVO);
        if (categoryStandardVO == null){
            String message = text + "类别失败，类别数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        if (categoryStandardVO.getIsDisplay().equals(enable)){
            String message = text + "类别失败，此类别已经处于" + text + "状态！";
            log.info("根据类别导航栏状态与要修改状态一致，抛出异常...");
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        Category category = new Category();
        category.setId(id)
                .setIsDisplay(enable);
        int rows = categoryMapper.updateById(category);
        if (rows != 1) {
            String message = "修改是否在导航栏失败！服务器忙，请稍后再试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        log.info("修改启用成功！");

    }


    @Override
    public List<CategoryTreeItemVO> listTree() {
       //有数据库获取全部类别对象
        List<CategoryListItemVO> categoryList = categoryMapper.list();
        //将List封装为Map，KEY为父级ID，VALUE为parentId为key，类别分组的list
        Map<Long,List<CategoryTreeItemVO>> allCategoryMap = transformListToMap(categoryList);
        //获取顶级树节点列表
        Long id = 0L;
        List<CategoryTreeItemVO> topTreeList = allCategoryMap.get(id);
        //遍历所有顶级节点
        for (CategoryTreeItemVO categoryTreeItemVO : topTreeList) {
            //装入节点的子节点集合
            fillChildren(categoryTreeItemVO,allCategoryMap);
        }
        return topTreeList;

    }



    /**
     * 使用递归，不断查找传入节点的字节蒂娜列表
     */
    private void fillChildren(CategoryTreeItemVO categoryTreeItemVO,Map<Long,List<CategoryTreeItemVO>> allCategoryMap){

        //根节点，无法获取子节点列表，表示该节点不是父节点
        List<CategoryTreeItemVO> subTreeList =allCategoryMap.get(categoryTreeItemVO.getValue());
        if (subTreeList == null){
            return;
        }
        for (CategoryTreeItemVO treeItemVO : subTreeList) {
            fillChildren(treeItemVO,allCategoryMap);
        }
        categoryTreeItemVO.setChildren(subTreeList);
    }


    /**
     * 以parentId为key,将类别分组
     */
    private Map<Long, List<CategoryTreeItemVO>> transformListToMap(List<CategoryListItemVO> categoryList){

        //以parentId为key，将类别分组
        Map<Long,List<CategoryTreeItemVO>> categoryListMap = new HashMap<>();
        for (CategoryListItemVO categoryListItemVO : categoryList) {
            //禁用的直接跳过
            if (categoryListItemVO.getEnable() == 0){
                continue;
            }

            //以该蕾姐父级ID为key集合
            List<CategoryTreeItemVO> categoryListTree = null;
            //Map中存在，直接取出
            if (categoryListMap.containsKey(categoryListItemVO.getParentId())){
                categoryListTree = categoryListMap.get(categoryListItemVO.getParentId());
            }
            else {
                //不存在，创建新集合
                categoryListTree = new ArrayList<>();
            }
            //转换为Tree的类，并装入集合
            CategoryTreeItemVO categoryTreeItemVO = new CategoryTreeItemVO();
            categoryTreeItemVO.setLabel(categoryListItemVO.getName())
                    .setValue(categoryListItemVO.getId());
            //装入List
            categoryListTree.add(categoryTreeItemVO);
            //装入Map
            categoryListMap.put(categoryListItemVO.getParentId(),categoryListTree);
        }
        return categoryListMap;

    }






    }




